----------------------------------------------------
--              LuaCalc Functions                 --
----------------------------------------------------
-- This file is part of luacalc (C) 2006 
-- This is probably the easiest place to contribute code to,
-- if you have any ideas for functions, send in a patch or an email.
--
-- NB: all function paramaters are likely to be passed as strings.
-- implicit or explicit coercion may be necessary.
--




--
-- keeps track of all documented functions.
-- 
function_list = {}

-- GUI only function, appends function to the edit->functions menu
add_to_help = add_to_help or function(_, _) end


--
-- It is helpful for a function to be directly associated with its documentation.
-- This function takes a single table as it's argument, registers it as a luacalc function 
-- and makes it callable by name. The table has a string member 'name', 
-- a function member 'call' and a string member 'help', where 'call' is the function 
-- to be evaluated and 'help' is it's documentation.

function luacalc_function(t)
	assert(t.call and t.help and t.name)
	_G[t.name]=t.call
	function_list[t.name]=t
	return t
end


-- Simple IF function 

luacalc_function{
	name = "IF",
	call = function(test,succeed,fail)
-- 		intuitive approach:
--		if test then
--			return succeed
--		else
--			return fail
--		end
--		lua approach:
		return test and succeed or fail
	end,
	help= "IF(cond, iftrue, <iffalse>): Evaluates cond, and returns iftrue if cond is true otherwise it returns iffalse "
}


luacalc_function{
	name = "NOT",
	call = function(val)
		return not(val)
	end,
	help = "NOT(val) returns true if val is not true, false otherwise"
}


luacalc_function{
	name="CONCATENATE",
	call = function(arg)
		return table.concat(arg)
	end,
	help="CONCATENTE(...) returns all arguments joined together as a single string."
}

luacalc_function{
	name="SUM",
call = function (arg)
	local total = 0
	for _, val in ipairs(arg) do
		total = total+val
	end
	return total
end,
help=[[
SUM(...):
returns the sum of all arguments. Use the range operator or reference a whole column.
All values must be numeric. eg:
SUM(A) --sum of all values in column A
SUM(A2:F2) -- sum values in row 2 from A2 to B2
]]
}


luacalc_function{
	name="AVERAGE",
call = function (arg)
   return SUM(arg)/#arg
end,
help=[[
AVERAGE(...):
returns the average(mean) of all arguments. Use the range operator or reference a whole column.
All values must be numeric. eg:
AVERAGE(A) --average value in column A
]]
}


function ISEMPTY(val)
   if (val=="" or not val) then return true else return false end
end

function TIME()
  return os.date()
end



luacalc_function{
	name = "RANDOM", 
	call = function(...)
		return math.random(unpack(arg))
	end,
help = [[
RANDOM([n], [m])
Calls the ansi C function: rand
both arguments are optional.
]]
}


fibs = {1, 1}
setmetatable(fibs, {
	__index=function(ta, k)
		--local key = tonumber(k)
		if k < 1 then
			ta[k] = 0
		else
			ta[k] = ta[k-2]+ta[k-1] 
		end
		return ta[k]
	end
})

-- gives the nth fibonacci number
luacalc_function{
	name = "FIB", 
	call = function(n)
		return fibs[tonumber(n) or 1]
	end,
help=[[FIB(n)
Returns the nth number in the fibonacci sequence where each number in the sequence is found by adding the previous two:
{1, 1, 2, 3, 5}
Results are cached for performance.
]]
}

luacalc_function{
	name = "ABS", 
	call = function(n)
		return math.abs(n)
	end,
help=[[ABS(n)
Returns the absolute value of n]]}


luacalc_function{
	name = "VERSION",
	call = function()
		return luacalc.version
	end,
	help="Returns the current version of luacalc"
}



-- some functions for playing sudoku

luacalc_function{
	name = "LEFT", 
	call = function(arg)
		local t = {'1', '2', '3', '4', '5', '6', '7', '8', '9'}
		for _, tab in next, arg do
			if type(tab)=="table" then
				for _, v in next, tab do
					--print(":"..v)
					local num = tonumber(v)
					if num then
						t[num]=''
					end
				end
			else
				local num = tonumber(tab)
					if num then
						t[num]=''
					end
			end
		end
		return CONCATENATE(t)
	end,
	help="Returns a string containing the numbers from 1-9 not given as an argument.\nUseful for playing sudoku - can tell what numbers are available in a certain area."
}



luacalc_function{
	name = "SAME", 
	call = function(a, b, c)
		local aa = {}
		string.foreach(a, function(_, letter) aa[letter] = true end)
		local bb = {}
		string.foreach(b, function(_, letter) bb[letter] = true end)
		local cc = {}
		string.foreach(c, function(_, letter) cc[letter] = true end)
		
		local res = {}
		for k, _ in pairs(aa) do
			if bb[k] and cc[k] then
				table.insert(res, k)
			end
		end
		table.sort(res)
		return CONCATENATE(res)
	end,
	help="Returns a string containing the numbers from 1-9 given in each string argument.\nUseful for playing sudoku - can tell what numbers are available in a row, col and box."
}




luacalc_function{
	name = "SELECT", 
	call = function(x1, y1, x2, y2)
		return luacalc.getselection{x1, y1, x2, y2}
	end,
	help=[[Returns the value(s) in a selection of cells indexed by numbers instead of A1 type syntax. Result is not necesarily displayable in a cell
and this function is designed to be used to pass arguments to other functions and be used with the $x and $y syntax.]]
}


